package main

import (
   // "encoding/binary"
    "fmt"
    "net"
    "time"
)

// 构建并返回一个协议帧
func buildProtocolFrame(adr, cid1, cid2 byte, info []byte) ([]byte, error) {
    soi := byte(0xA5)                // 假设 SOI 固定值
    ver := byte(0x01)                // 假设协议版本
    length := uint16(len(info) * 2)  // 长度字段，INFO 部分的字节数 × 2
    chksum := calculateChecksum([]byte{ver, adr, cid1, cid2, byte(length >> 8), byte(length)}, info)
    eoi := byte(0x5A)                // 假设 EOI 固定值

    frame := []byte{soi, ver, adr, cid1, cid2, byte(length >> 8), byte(length & 0xFF)}
    frame = append(frame, info...)
    frame = append(frame, byte(chksum >> 8), byte(chksum & 0xFF), eoi)
    return frame, nil
}

// 计算 CHKSUM 的辅助函数
func calculateChecksum(header []byte, info []byte) uint16 {
    var sum uint16
    for _, b := range header {
        sum += uint16(b)
    }
    for _, b := range info {
        sum += uint16(b)
    }
    return ^sum + 1 // 使用补码校验
}

// 发送和接收协议帧
func communicateWithSM(conn net.Conn, adr, cid1, cid2 byte, info []byte) error {
    frame, err := buildProtocolFrame(adr, cid1, cid2, info)
    if err != nil {
        return fmt.Errorf("构建协议帧失败: %v", err)
    }

    // 发送协议帧
    _, err = conn.Write(frame)
    if err != nil {
        return fmt.Errorf("发送协议帧失败: %v", err)
    }
    fmt.Println("发送协议帧:", frame)

    // 设置读取超时并接收响应
    conn.SetReadDeadline(time.Now().Add(2 * time.Second))
    response := make([]byte, 256)
    n, err := conn.Read(response)
    if err != nil {
        return fmt.Errorf("接收响应失败: %v", err)
    }

    // 输出响应数据（根据协议格式进一步解析）
    fmt.Println("接收到的响应:", response[:n])
    return nil
}

func main() {
    targetAddr := "192.168.1.100:5020" // 假设设备地址和端口

    conn, err := net.Dial("tcp", targetAddr)
    if err != nil {
        fmt.Println("连接失败:", err)
        return
    }
    defer conn.Close()

    // 示例命令信息（ADR, CID1, CID2, 和 INFO）
    adr, cid1, cid2 := byte(0x01), byte(0x10), byte(0x20)
    info := []byte{0x30, 0x40} // 假设的 INFO 内容

    if err := communicateWithSM(conn, adr, cid1, cid2, info); err != nil {
        fmt.Println("通信失败:", err)
    }
}
